﻿package net.wangit.framework.action;

import net.wangit.MapList;
import net.wangit.Row;
import net.wangit.framework.config.DomainsSettings;
import net.wangit.framework.util.InterceptorLoader;
import net.wangit.jdbc.DB;
import net.wangit.jdbc.ServerAccessException;
import net.wangit.jdbc.Type;
import net.wangit.jdbc.util.DBHelper;
import net.wangit.util.Checker;
import net.wangit.view.unit.UnitComponent;
import net.wangit.view.unit.UnitFactory;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


public class ActionMappingFactory {

	private static final Log log = LogFactory
			.getLog(net.wangit.framework.action.ActionMappingFactory.class);
	private static final String SQL = "select * from ELEMENT where uid=? and eid=? and a=1";

	public ActionMappingFactory() {
	}

	//从缓存中获取ActionMapping,如缓存中不存在则从数据库中加载
	public static synchronized ActionMapping getActionMapping(String domain,
			String unitId, String actionId) {
		ActionMapping mapping = ActionMappingCache.get(domain, unitId, actionId);
		if (mapping == null) {
			mapping = createActionMapping(domain, unitId, actionId);
			ActionMappingCache.put(domain, unitId, actionId, mapping);
		}
		return mapping;
	}

	//从数据库中加载ActionMapping
	private static ActionMapping createActionMapping(String domain,
			String unitId, String actionId) {
		DB db = DBHelper.getDomainDB(domain);
		MapList list;
		try {
			list = db.query(SQL, new String[] { unitId, actionId }, new int[] {
					Type.VARCHAR, Type.VARCHAR });
		} catch (Exception e) {
			log.error(
					(new StringBuilder("could not query element in server: "))
							.append(domain).toString(), e);
			throw new ServerAccessException((new StringBuilder(
					"could not query element in server: ")).append(domain)
					.toString(), e);
		}
		if (Checker.isEmpty(list)) {
			log.warn((new StringBuilder("Not found ActionMapping for unit '"))
					.append(unitId).append("' with action '").append(actionId)
					.append("'").toString());
			return null;
		}
		Row row = list.getRow(0);
		ActionMapping mapping = new ActionMapping();
		mapping.setDomain(domain);
		mapping.setUnitId(unitId);
		UnitComponent uc = UnitFactory.getUnitWithoutClone(domain, unitId);
		mapping.setUnitName(uc.getName());
		mapping.setGroupId(uc.getGroupId());
		mapping.setId(actionId);
		mapping.setName(row.get("n"));
		mapping.setPublished(uc.isPublished());
		String proxy = row.get("ap");
		if (Checker.isEmpty(proxy))
			proxy = DomainsSettings.getDefaultProxy(domain);
		mapping.setProxy(proxy);
		String action = row.get("aa");
		if (Checker.isEmpty(action))
			action = DomainsSettings.getDefaultAction(domain);
		mapping.setAction(action);
		String interceptors = row.get("ai");
		try {
			mapping.setInterceptors(InterceptorLoader
					.loadActionInterceptors(interceptors));
		} catch (Exception e) {
			log.error(
					(new StringBuilder("could not load action interceptors: "))
							.append(interceptors).append(" for ")
							.append(domain).append("/").append(unitId).append(
									"/").append(actionId).toString(), e);
			throw new ActionConfigurationException((new StringBuilder(
					"could not load action interceptors: ")).append(
					interceptors).toString(), domain, unitId, actionId,
					"action interceptors", e);
		}
		mapping.setValidateUnits(row.get("av"));
		mapping.setCommand(row.get("ac"));
		mapping.setParameter(row.get("c1"));
		String datasource = row.get("ad");
		if (Checker.isEmpty(datasource))
			datasource = DomainsSettings.getDatasource(domain);
		mapping.setDatasource(datasource);
		mapping.setHasAccessPrivilege("1".equals(row.get("au")));
		mapping.setSupportLog(!"0".equals(row.get("i1")));
		mapping.setRedirect(!"0".equals(row.get("arr")));
		mapping.setTokenEnabled("1".equals(row.get("at")));
		mapping.setScript(row.get("ars"));
		mapping.setSuccessfulForward(row.get("asf"));
		mapping.setFailedForward(row.get("aff"));
		mapping.setSuccessfulMessage(row.get("asm"));
		mapping.setFailedMessage(row.get("afm"));
		if (log.isDebugEnabled())
			log.debug((new StringBuilder("create mapping for: "))
					.append(domain).append("/").append(unitId).append("/")
					.append(actionId).toString());
		return mapping;
	}

}
